interface Items {
  id: number
  pid: number
}

interface TreeItems extends Items {
  children: Array<TreeItems>
}

type ItemMap = Record<string, TreeItems>

/**
 * @description arr transfor tree
 * @param {Array<T>} items arr
 * @returns {Array<TreeItems>} tree
 * @example
  ```
  let arr = [
    { id: 1, name: '部门1', pid: 0 },
    { id: 3, name: '部门3', pid: 1 },
    { id: 2, name: '部门2', pid: 1 },
    { id: 4, name: '部门4', pid: 3 },
    { id: 5, name: '部门5', pid: 4 },
    { id: 6, name: '部门8', pid: 9 },
    { id: 7, name: '部门8', pid: 15 },
  ]
  ```
 */
export const arrayToTree = <T extends Items>(items: Array<T>): Array<TreeItems> => {
  const result = []
  const itemMap: ItemMap = {}

  for (const item of items) {
    itemMap[item.id] = { ...item, children: [] }
  }

  for (const item of items) {
    const { id, pid } = item
    const treeItem = itemMap[id]
    if (pid === 0) {
      result.push(treeItem)
    } else {
      // eslint-disable-next-line no-lonely-if
      if (itemMap[pid]) {
        itemMap[pid].children.push(treeItem)
      }
    }
  }
  return result
}

/**
 * @deprecated
 * @description arr transfor tree recomend use arrayToTree - use `arrayToTree`
 * @param {Array<T>} items - arr
 * @param {Array<TreeItems>} result - default: `[]`
 * @param {number} pid - parentId. default: `0`
 * @returns {Array<TreeItems>} tree
 *
 */
export const arrToTree = <T extends Items>(arr: Array<T>, result: Array<TreeItems> = [], pid = 0): Array<TreeItems> => {
  for (const item of arr) {
    if (item.pid === pid) {
      const pItem = { ...item, children: [] }
      result.push(pItem)
      arrToTree(arr, pItem.children, item.id)
    }
  }
  return result
}

/**
 * @description tree transfor arrr
 * @param {Array<TreeItems>} tree
 * @returns {Array} - 扁平化数据
 */
export const treeToArray = <T extends Items>(tree: Array<TreeItems>): Array<T> => {
  const result: Array<T> = []

  const flatten = (node: TreeItems) => {
    const { children, ...item } = node
    result.push(item as unknown as T)
    if (children && children.length > 0) {
      for (const child of children) {
        flatten(child) // 递归处理子节点
      }
    }
  }

  for (const node of tree) {
    flatten(node)
  }

  return result
}
